// ignore_for_file: avoid_single_cascade_in_expression_statements

library flutter_client_sse;

import 'dart:async';
import 'dart:convert';
import 'dart:ffi';
import 'dart:ui';
import 'package:http/http.dart' as http;
import 'package:oktoast/oktoast.dart';
import 'package:sj001/model/revMsgModel.dart';

import 'constants/sse_request_type_enum.dart';

part 'sse_event_model.dart';

/// A client for subscribing to Server-Sent Events (SSE).
class SSEClient {
  static http.Client _client = new http.Client();

  /// Retry the SSE connection after a delay.
  ///
  /// [method] is the request method (GET or POST).
  /// [url] is the URL of the SSE endpoint.
  /// [header] is a map of request headers.
  /// [body] is an optional request body for POST requests.
  /// [streamController] is required to persist the stream from the old connection
  // static void _retryConnection(
  //     {required SSERequestType method,
  //     required String url,
  //     required Map<String, String> header,
  //     required StreamController<SSEModel> streamController,
  //     Map<String, dynamic>? body}) {
  //   print('---RETRY CONNECTION---');
  //   Future.delayed(Duration(seconds: 5), () {
  //     subscribeToSSE(
  //       method: method,
  //       url: url,
  //       header: header,
  //       body: body,
  //       oldStreamController: streamController,
  //     );
  //   });
  // }

  /// Subscribe to Server-Sent Events.
  ///
  /// [method] is the request method (GET or POST).
  /// [url] is the URL of the SSE endpoint.
  /// [header] is a map of request headers.
  /// [body] is an optional request body for POST requests.
  ///
  /// Returns a [Stream] of [SSEModel] representing the SSE events.
  static subscribeToSSE({
    required SSERequestType method,
    required String url,
    required Map<String, String> header,
    Map<String, dynamic>? body,
    Function(RevMsgModel)? onData,
    Function(String)? onError,
    Function(RevMsgModel)? onDataError,
    Function(RevMsgModel)? onDone,
  }) {
    try {
      _client = http.Client();
      var request = http.Request(
        method == SSERequestType.GET ? "GET" : "POST",
        Uri.parse(url),
      );

      /// Adding headers to the request
      header.forEach((key, value) {
        request.headers[key] = value;
      });

      /// Adding body to the request if exists
      if (body != null) {
        request.body = jsonEncode(body);
      }

      Future<http.StreamedResponse> response = _client.send(request);

      bool hasReturn = false;
      int i = 0;
      Timer timer = Timer.periodic(const Duration(seconds: 2), (timer) {
        i+=2;
        print(i);
        if (i>=30 && !hasReturn){
          onError?.call('error: network error!');
          showToast('network error!');
          unsubscribeFromSSE();
        }
      });

      response.asStream().listen((data) {
        data.stream
          ..transform(const Utf8Decoder())
              .transform(const LineSplitter())
              .listen(
            (dataLine) {
              print(dataLine);
              if (dataLine.isEmpty) return;
              // 判断 是否为data:开头 // 如果是 那么请求正常，否，那么请求失败，借书请求
              String prefix = 'data:';
              if(dataLine.startsWith(prefix)){
                String rsp = dataLine.substring(prefix.length);
                RevMsgModel rspModel = RevMsgModel.fromJson(jsonDecode(rsp));
                if (rspModel.isEnd){
                  hasReturn = true;
                  onDone?.call(rspModel);
                  timer.cancel();
                  unsubscribeFromSSE();
                }else if (rspModel.isError){
                  onDataError?.call(rspModel);
                  timer.cancel();
                  unsubscribeFromSSE();
                }else {
                  hasReturn = true;
                  timer.cancel();
                  onData?.call(rspModel);
                }
              }else{

              }
            },
            onError: (e, s) {
              unsubscribeFromSSE();
              timer.cancel();
              print(e);
              onError?.call(e.toString());
            },
          );
      }, onError: (e, s) {
        print(e);
        onError?.call(e.toString());
        timer.cancel();
        unsubscribeFromSSE();
      });
    } catch (e) {
      print(e);
      onError?.call(e.toString());
    }
  }

  /// Unsubscribe from the SSE.
  static void unsubscribeFromSSE() {
    print('主动断开');
    _client.close();
  }
}
// 5956a39e-1b1a-413c-adc5-07a8dfeccf94